﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using T.FAS.Runtime.Action.Dao;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Expression.Entity;
using ActionType = T.FAS.Runtime.Metadata.Entity.ActionType;

namespace T.FAS.Runtime.Action.ExpressionPlugin
{
    public class ExpressionPluginManager
    {
        public BaseProvider provider = null;

        /// <summary>
        /// 长度
        /// </summary>
        public const string ExprExt_Length = "AttrLength";
        /// <summary>
        /// 是否必填
        /// </summary>
        public const string ExprExt_IsRequired = "AttrIsRequired";
        /// <summary>
        /// 精度
        /// </summary>
        public const string ExprExt_Precision = "AttrPrecision";
        /// <summary>
        /// 默认值
        /// </summary>
        public const string ExprExt_DefaultValue = "AttrDefaultValue";
        /// <summary>
        /// 字段属性类型，用于标识是否是外键关联字段
        /// </summary>
        public const string ExprExt_AttributeType = "AttributeType";
        /// <summary>
        /// 字段数据类型
        /// </summary>
        public const string ExprExt_DataType = "DataType";
        /// <summary>
        /// 是否是系统预置属性，例如DQ的查询条件中，会有系统默认的查询条件
        /// </summary>
        public const string ExprExt_IsSysDefault = "IsSysDefault";
        /// <summary>
        /// 扩展属性字段：是否SDO
        /// </summary>
        public const string ExprExt_IsSDO = "IsSDO";
        /// <summary>
        /// 扩展属性字段：如果是SDO，此字段保存关联的DQID
        /// </summary>
        public const string ExprExt_SDORelatedID = "SDORelatedID";
        /// <summary>
        /// 扩展属性集合
        /// </summary>

        public static List<string> ExprExtList = new List<string>()
        {
            ExprExt_IsSDO,ExprExt_SDORelatedID
        };


        public TSchema UpdateExprItemChildren(ExprItem item, bool IsContainExt = false)
        {
            if (item.ItemType == ItemType.Action)
            {
                return BuildTSchemaForAction(item, IsContainExt);
            }
            else 
            {
                return BuildTSchemaForOther(item, IsContainExt);
            }
        }
        private TSchema BuildTSchemaForOther(ExprItem item, bool IsContainExt = false)
        {
            TSchema scheme = new TSchema();
            switch (item.ItemType)
            {
                case ItemType.DO:
                    {
                        var dataobject = provider.GetMetaDataContentByType(item.ID,ProviderMetadataType.DO) as DataObject; 
                        UpdateDataObjectExprItem(item, dataobject, IsContainExt);
                    }
                    break;
                case ItemType.EO:
                    {
                        var eo = provider.GetMetaDataContentByType(item.ID, ProviderMetadataType.EO) as EntityObject;
                        UpdateEntityObjectExprItem(item, eo, IsContainExt);
                    }
                    break;
                case ItemType.CDO:
                default:
                    {
                        var cdo = provider.GetMetaDataContentByType(item.ID, ProviderMetadataType.CDO) as CompositeDataObject;
                        UpdateCDOExprItem(item, cdo, IsContainExt);
                    }
                    break;
            }
            return scheme;
        }

        private void UpdateDataObjectExprItem(ExprItem item, DataObject dataobject, bool IsContainExt = false)
        {
            IRefSchemaEntity refSchemaEntity = provider.RefSchemaExprUtil.GetRefSchemaEntity(dataobject);
            item.Children = new List<ExprItem>();
            if (item.ValueType == DataType.List)
            {
                string exprContent = $"Schema.DO.{dataobject.Code}";
                var currentNode = new ExprItem()
                {
                    ID = "Current",
                    Code = "Current",
                    Name = "Current",
                    ParentID = item.ID,
                    DisplayName = item.DisplayName + ".Current",
                    RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(exprContent),
                    RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, exprContent, false),
                    DataModels = dataobject.Code,
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    ItemType = ItemType.Object
                };
                currentNode.Children = new List<ExprItem>();
                var index = 0;
                foreach (var column in dataobject.Columns)
                {
                    string doColExprContent = $"Schema.DO.{dataobject.Code}.Columns.{column.ColumnName}";
                    var columnNode = new ExprItem()
                    {
                        ID = column.ID,
                        Code = column.ColumnName,
                        Name = column.DisplayName,
                        ParentID = currentNode.ID,
                        DisplayName = currentNode.DisplayName + "." + column.ColumnName,
                        RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(doColExprContent),
                        RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, doColExprContent, true),
                        DataModels = column.ColumnName,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), column.IsFkColumn ? column.GetFKDataObjectPkColumnApplicationDataType(): column.ApplicationDataType, true),
                        ItemType = ItemType.Attribute
                    };
                    //是否需要包含扩展属性
                    if (IsContainExt)
                    {
                        var extDic = new Dictionary<string, object>();
                        extDic.Add(ExpressionPluginManager.ExprExt_Length, column.Length);
                        extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, column.IsNullable ? false : true);
                        extDic.Add(ExpressionPluginManager.ExprExt_Precision, column.Precision);
                        extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, column.DefaultValue);
                        columnNode.ExprExt = extDic;
                    }
                    currentNode.Children.Add(columnNode);
                    index++;
                }
                item.Children = new List<ExprItem>() { currentNode };
            }
            else if (item.ValueType == DataType.Record)
            {
                var index = 0;
                foreach (var column in dataobject.Columns)
                {
                    string exprContent = $"Schema.DO.{dataobject.Code}.Columns.{column.ColumnName}";
                    var columnNode = new ExprItem()
                    {
                        ID = column.ID,
                        Code = column.ColumnName,
                        Name = column.DisplayName,
                        ParentID = item.ID,
                        DisplayName = item.DisplayName + "." + column.ColumnName,
                        RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(exprContent),
                        RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, exprContent, true),
                        DataModels = column.ColumnName,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), column.IsFkColumn ? column.GetFKDataObjectPkColumnApplicationDataType(): column.ApplicationDataType, true),
                        ItemType = ItemType.Attribute
                    };
                    item.Children.Add(columnNode);
                    index++;
                }
            }
        }

        /// <summary>
        /// 为EO类型单独创建ExprItem结构
        /// </summary>
        /// <param name="item"></param>
        /// <param name="entityObject"></param>
        private void UpdateEntityObjectExprItem(ExprItem item, EntityObject entityObject, bool IsContainExt)
        {
            IRefSchemaEntity refSchemaEntity = provider.RefSchemaExprUtil.GetRefSchemaEntity(entityObject);
            item.Children = new List<ExprItem>();
            if (item.ValueType == DataType.List)
            {
                string exprContent = $"Schema.EO.{entityObject.Code}.Attrs.{item.Code}";
                var currentNode = new ExprItem()
                {
                    ID = "Current",
                    Code = "Current",
                    Name = "Current",
                    ParentID = item.ID,
                    DisplayName = item.DisplayName + ".Current",
                    RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(exprContent),
                    RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, exprContent, false),
                    DataModels = entityObject.Code,
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    ItemType = ItemType.Object
                };
                currentNode.Children = new List<ExprItem>();
                var index = 0;
                foreach (EntityObjectAttribute attr in entityObject.EntityObjectAttributes)
                {
                    string eoAttrExprContent = $"Schema.EO.{entityObject.Code}.Attrs.{item.Code}";
                    var attrNode = new ExprItem()
                    {
                        ID = attr.ID,
                        Code = attr.Code,
                        Name = attr.Name,
                        ParentID = currentNode.ID,
                        DisplayName = currentNode.DisplayName + "." + attr.Code,
                        RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(eoAttrExprContent),
                        RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, eoAttrExprContent, true),
                        DataModels = attr.Code,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), attr.DataType, true),
                        ItemType = ItemType.Attribute
                    };
                    //是否需要包含扩展属性
                    //if (IsContainExt)
                    //{
                    //    var extDic = new Dictionary<string, object>();
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Length, attr.Length);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, attr.IsRequired);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Precision, attr.Precision);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, attr.DefaultValue);
                    //    attrNode.ExprExt = extDic;
                    //}
                    currentNode.Children.Add(attrNode);
                    index++;
                }
                item.Children = new List<ExprItem>() { currentNode };
            }
            else if (item.ValueType == DataType.Record)
            {
                var index = 0;
                foreach (EntityObjectAttribute attr in entityObject.EntityObjectAttributes)
                {
                    string eoAttrExprContent = $"Schema.EO.{entityObject.Code}.Attrs.{item.Code}";
                    var columnNode = new ExprItem()
                    {
                        ID = attr.ID,
                        Code = attr.Code,
                        Name = attr.Name,
                        ParentID = item.ID,
                        DisplayName = item.DisplayName + "." + attr.Code,
                        RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(eoAttrExprContent),
                        RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, eoAttrExprContent, true),
                        DataModels = attr.Code,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), attr.DataType, true),
                        ItemType = ItemType.Attribute
                    };
                    //是否需要包含扩展属性
                    //if (IsContainExt)
                    //{
                    //    var extDic = new Dictionary<string, object>();
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Length, attr.Length);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, attr.IsRequired);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Precision, attr.Precision);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, attr.DefaultValue);
                    //    columnNode.ExprExt = extDic;
                    //}
                    item.Children.Add(columnNode);
                    index++;
                }
            }
        }

        /// <summary>
        /// 为cdo类型单独创建ExprItem结构
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cdo"></param>
        private void UpdateCDOExprItem(ExprItem item, CompositeDataObject cdo, bool IsContainExt = false)
        {
            IRefSchemaEntity refSchemaEntity = provider.RefSchemaExprUtil.GetRefSchemaEntity(cdo);
            var schema = cdo.BuildSchema();
            if (item.ValueType == DataType.List)
            {
                var currentCode = "Current";
                //List的需要构造Current节点
                string exprContent = $"Schema.CDO.{cdo.Code}";
                var currentNode = new ExprItem()
                {
                    ID = currentCode,
                    Code = currentCode,
                    Name = currentCode,
                    DataModels = cdo.Code,
                    DisplayName = item.DisplayName + "." + currentCode,
                    RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(exprContent),
                    RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, exprContent, false),
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    ItemType = ItemType.Object,
                    ParentID = item.ID,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    Children = new List<ExprItem>()
                };
                BuildTEntityExprItem(currentNode, schema.Entity, IsContainExt, cdo);
                item.Children = new List<ExprItem>() { currentNode };
            }
            else
            {
                BuildTEntityExprItem(item, schema.Entity, IsContainExt, cdo);
            }
        }
        private void BuildTEntityExprItem(ExprItem parentItem, TEntity entity, bool IsContainExt = false, IMetaDataContent metaDataContent = null)
        {
            if (entity == null)
                return;

            IRefSchemaEntity refSchemaEntity = provider.RefSchemaExprUtil.GetRefSchemaEntity(metaDataContent);
            //针对DQ有多个DO的情况，需要单独处理
            if (entity.MetadataType == TEntityType.DQ)
            {
                //处理一个DQ下有多个DO
                var subEntitys = entity.Attributes.FindAll(x => x.DataType == DataType.List || x.DataType == DataType.Record);
                if (subEntitys != null && subEntitys.Count > 1)
                {
                    var itemIndex = 0;
                    foreach (TAttribute item in subEntitys)
                    {
                        var itemNode = new ExprItem()
                        {
                            ID = item.Entity.MetadataID,
                            Code = item.Entity.MetadataCode,
                            Name = item.Entity.MetadataName,
                            DisplayName = parentItem.DisplayName + "." + item.Entity.MetadataCode,
                            RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(item.RefSchemaExpr),
                            DataModels = item.Entity.MetadataCode,
                            HelpInfo = item.Entity.MetadataCode,
                            SortOrder = itemIndex,
                            ValueType = item.Entity.ResultType,
                            ExprMetaDataID = parentItem.ExprMetaDataID,
                            ParentID = parentItem.ID,
                            ItemType = GetItemTypeByTEntityType(item.Entity.MetadataType)
                        };
                        if (item.Entity.Attributes != null && item.Entity.Attributes.Count > 0)
                        {
                            itemNode.IsLeaf = false;
                            BuildPropertyExprItem(itemNode, item.Entity, IsContainExt, metaDataContent);
                        }
                        else
                        {
                            itemNode.IsLeaf = true;
                        }
                        itemNode.RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, item.RefSchemaExpr, itemNode.IsLeaf);
                        parentItem.Children.Add(itemNode);
                        itemIndex++;
                    }
                }
                //处理一个DQ下只有一个DO
                else if (subEntitys != null && subEntitys.Count.Equals(1))
                {
                    if (subEntitys[0].Entity.Attributes != null && subEntitys[0].Entity.Attributes.Count > 0)
                    {
                        BuildTEntityExprItem(parentItem, subEntitys[0].Entity, metaDataContent: metaDataContent);
                    }
                }
                //处理Attribute
                var attributes = entity.Attributes.FindAll(x => x.DataType != DataType.List && x.DataType != DataType.Record);
                if (attributes != null && attributes.Count > 0)
                {
                    var attrIndex = 0;
                    foreach (TAttribute attr in attributes)
                    {
                        //跳过辅助语言字段
                        if (attr.IsNeedHideField(provider.IsDev)) continue;
                        var itemNode = new ExprItem()
                        {
                            ID = attr.ID,
                            Code = attr.Code,
                            Name = attr.Name,
                            DisplayName = parentItem.DisplayName + "." + attr.Code,
                            RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(attr.RefSchemaExpr),
                            RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, attr.RefSchemaExpr, true),
                            HelpInfo = attr.Code,
                            SortOrder = attrIndex,
                            ValueType = attr.DataType,
                            ExprMetaDataID = parentItem.ExprMetaDataID,
                            ParentID = parentItem.ID,
                            IsLeaf = true,
                            ItemType = GetItemTypeByTEntityType(TEntityType.Attribute)
                        };
                        parentItem.Children.Add(itemNode);
                        attrIndex++;
                    }
                }
            }
            //针对非DQ的,主节点不需要体现,直接体现属性字段
            else
            {
                if (entity.Attributes != null && entity.Attributes.Count > 0)
                {
                    BuildPropertyExprItem(parentItem, entity, IsContainExt, metaDataContent);
                }
                //var itemNode = new ExprItem()
                //{
                //    ID = entity.MetadataID,
                //    Name = entity.MetadataCode,
                //    DisplayName = parentItem.DisplayName + "." + entity.MetadataCode,
                //    HelpInfo = entity.MetadataCode,
                //    SortOrder = 0,
                //    ValueType = entity.ResultType,
                //    ExprMetaDataID = parentItem.ExprMetaDataID,
                //    ParentID = parentItem.ID,
                //    ItemType = GetItemTypeByTEntityType(entity.MetadataType)
                //};
                //if (entity.Attributes != null && entity.Attributes.Count > 0)
                //{
                //    BuildPropertyExprItem(itemNode, entity);
                //}
                //parentItem.Children.Add(itemNode);
            }
        }
        private TSchema BuildTSchemaForAction(ExprItem item, bool IsContainExt = false)
        {
            var schema = new TSchema();
            var action = GetActionMetaDataByID(item.ID);
            if (action != null)
            {
                if (action.ActionType == ActionType.CDO)
                {
                    var cdo = new T.FAS.Runtime.DataModel.Plugin.CompositeDataObjectManager().GetMetaDataContent(action.RelatedMetaDataID) as CompositeDataObject;
                    schema = cdo.BuildSchema();
                    action.ActionSchemaRefresh(schema);
                    UpdateExprItem(item, action, schema, IsContainExt: IsContainExt);
                    UpdateHelpInfo(item);
                }
                else
                {
                    if (action.MethodParams != null && action.MethodParams.Count > 0)
                    {
                        var outParam = action.MethodParams.Find(x => x.ParamType == ParamType.Out);
                        if (outParam != null && outParam.ParamSourceType == ParamSourceType.EO)
                        {
                            var eo = new DataModel.Plugin.EntityObjectManager().GetMetaDataContent(action.RelatedMetaDataID) as EntityObject;
                            schema = eo.BuildSchema();
                            action.ActionSchemaRefresh(schema);
                            UpdateExprItem(item, action, schema, IsContainExt: IsContainExt);
                            UpdateHelpInfo(item);
                        }
                    }
                }
            }
            return schema;
        }
        private void BuildPropertyExprItem(ExprItem parentItem, TEntity entity, bool IsContainExt = false, IMetaDataContent metaDataContent = null)
        {
            if (entity == null || entity.Attributes == null || entity.Attributes.Count <= 0)
                return;
            IRefSchemaEntity refSchemaEntity = provider.RefSchemaExprUtil.GetRefSchemaEntity(metaDataContent);
            var proIndex = 0;
            foreach (var attr in entity.Attributes.OrderBy(x => x.SortOrder))
            {
                if (attr.DataType == DataType.Record)
                {
                    var pRecordNode = new ExprItem()
                    {
                        ID = attr.Entity.MetadataCode,
                        Code = attr.Entity.MetadataCode,
                        Name = attr.Entity.MetadataName,
                        DisplayName = parentItem.DisplayName + "." + attr.Entity.MetadataCode,
                        RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(attr.RefSchemaExpr),
                        RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, attr.RefSchemaExpr, false),
                        DataModels = attr.Entity.MetadataCode,
                        ItemType = ItemType.Object,
                        HelpInfo = attr.Name,
                        SortOrder = proIndex,
                        IsLeaf = false,
                        ValueType = DataType.Record
                    };
                    BuildPropertyExprItem(pRecordNode, attr.Entity, IsContainExt, metaDataContent);
                    parentItem.Children.Add(pRecordNode);
                }
                else if (attr.DataType == DataType.List)
                {
                    //增加List节点
                    attr.Entity.ListTypeMethods.OrderBy(x => x.SortOrder).ToList().ForEach(method =>
                    {
                        BuildListTypeMethodExprItem(parentItem, method, attr.Entity, IsContainExt, metaDataContent: metaDataContent);
                    });
                }
                else
                {
                    //跳过辅助语言字段
                    if (attr.IsNeedHideField(provider.IsDev)) continue;
                    var pNode = new ExprItem()
                    {
                        ID = attr.ID,
                        Code = attr.Code,
                        Name = attr.Name,
                        DisplayName = parentItem.DisplayName + "." + attr.Code,
                        RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(attr.RefSchemaExpr),
                        RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, attr.RefSchemaExpr, true),
                        ItemType = ItemType.Attribute,
                        HelpInfo = parentItem.DisplayName + "." + attr.Code,
                        SortOrder = proIndex,
                        ValueType = attr.DataType,
                        ExprMetaDataID = parentItem.ExprMetaDataID,
                        IsLeaf = true,
                    };
                    //是否需要包含扩展属性
                    if (IsContainExt)
                    {
                        var extDic = new Dictionary<string, object>();
                        extDic.Add(ExpressionPluginManager.ExprExt_Length, attr.Length);
                        extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, attr.IsRequired);
                        extDic.Add(ExpressionPluginManager.ExprExt_Precision, attr.Precision);
                        extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, attr.DefaultValue);
                        pNode.ExprExt = extDic;
                    }
                    parentItem.Children.Add(pNode);
                }
                proIndex++;
            }
        }

        private void BuildListTypeMethodExprItem(ExprItem parentItem, TListMethod method, TEntity entity, bool isRoot = false, bool IsContainExt = false, IMetaDataContent metaDataContent = null)
        {
            IRefSchemaEntity refSchemaEntity = provider.RefSchemaExprUtil.GetRefSchemaEntity(metaDataContent);
            var item = new ExprItem();
            if (!isRoot && method.Code.ToLower().Equals("list"))
            {
                bool isLeafFlag = (method.SubMethods == null || method.SubMethods.Count <= 0) ? true : false;
                item = new ExprItem()
                {
                    ID = entity.MetadataID,
                    Code = entity.MetadataCode,
                    Name = entity.MetadataName,
                    DisplayName = parentItem.DisplayName + "." + entity.MetadataCode,
                    RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(entity.RefSchemaExpr),
                    RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, entity.RefSchemaExpr, isLeafFlag),
                    ValueType = method.ReturnDataType,
                    ItemType = ItemType.Object,
                    SortOrder = method.SortOrder,
                    ExprMetaDataID = parentItem.ExprMetaDataID,
                    ParentID = parentItem.ID,
                    IsLeaf = isLeafFlag,
                    DataModels = entity.MetadataCode,
                };
            }
            else
            {
                item = new ExprItem()
                {
                    ID = Guid.NewGuid().ToString(),
                    Code = method.Code,
                    Name = method.Code,
                    DisplayName = parentItem.DisplayName + "." + method.Code,
                    RefSchemaExpr = "not supported path",
                    ValueType = method.ReturnDataType,
                    ItemType = ItemType.Object,
                    HelpInfo = parentItem.DisplayName + "." + method.Code,
                    SortOrder = method.SortOrder,
                    ExprMetaDataID = parentItem.ExprMetaDataID,
                    ParentID = parentItem.ID,
                    IsLeaf = (method.SubMethods == null || method.SubMethods.Count <= 0) ? true : false,
                };
                if (entity.Attributes != null && entity.Attributes.Count > 0)
                {
                    item.DataModels = string.Join(",", entity.MetadataCode);
                }
            }
            if (!string.IsNullOrEmpty(method.JSFunc) && method.JSFunc.ToLower().Equals(("@entity" + entity.MetadataCode).ToLower()))
            {
                item.IsLeaf = false;
                //构造Current下级的Entity结构
                BuildTEntityExprItem(item, entity, IsContainExt, metaDataContent);
            }
            else
            {
                if (method.SubMethods != null && method.SubMethods.Count > 0)
                {
                    method.SubMethods.ForEach(m =>
                    {
                        BuildListTypeMethodExprItem(item, m, entity, IsContainExt: IsContainExt, metaDataContent: metaDataContent);
                    });
                }
            }
            parentItem.Children.Add(item);
        }
        private ActionMetaData GetActionMetaDataByID(string id)
        {
            var action = new ActionMetaDataManager().GetMetaDataContent(id);
            return action;
        }
        private void UpdateExprItem(ExprItem exprItem, ActionMetaData action, TSchema schema, string exprPreFix = "Action.", bool IsContainExt = false)
        {
            if (schema == null)
                return;
            IRefSchemaEntity refSchemaEntity = provider.RefSchemaExprUtil.GetRefSchemaEntity(action);

            DataType dType = default;
            switch (action.ReturnValueType)
            {
                case ReturnValueType.List:
                    dType = DataType.List;
                    break;
                case ReturnValueType.Record:
                    dType = DataType.Record;
                    break;
                default:
                    return;
            }
            exprItem.Code = action.Code;
            exprItem.Name = action.Name;
            exprItem.IsLeaf = false;
            exprItem.HelpInfo = action.Name;
            exprItem.ItemType = ItemType.Action;
            exprItem.ValueType = action.ReturnValueType.Equals(ReturnValueType.List) ? DataType.List : DataType.Record;
            //填充DataModels
            if (schema.MetadataType == TEntityType.DQ)
            {
                if (schema.Entity != null && schema.Entity.Attributes != null && schema.Entity.Attributes.Count > 0)
                {
                    var subEntities = schema.Entity.Attributes.FindAll(x => x.DataType == DataType.List || x.DataType == DataType.Record);
                    if (subEntities != null && subEntities.Count > 0)
                    {
                        exprItem.DataModels = string.Join(",", subEntities.Select(x => x.MetadataCode));
                    }
                }
            }
            else
            {
                if (schema.Entity != null)
                {
                    exprItem.DataModels = schema.Entity.MetadataCode;
                }
            }

            //构造入参集合
            exprItem.ExprFuncItemParamList = new List<ExprFuncItemParam>();
            var inParams = action.MethodParams.FindAll(x => x.ParamType == ParamType.In );
            inParams.ForEach(p =>
            {
                int index = 0;
                exprItem.ExprFuncItemParamList.Add(new ExprFuncItemParam()
                {
                    ID = Guid.NewGuid().ToString(),
                    ExprItemID = exprItem.ID,
                    Code = p.Code,
                    Name = p.Name,
                    SortOrder = index,
                    DataType = p.SysDataType,
                });
                index++;
            });

            exprItem.DisplayName = exprPreFix + action.Code + $"({string.Join(",", inParams.Select(p => p.Code))})";
            string exprContent = $"Schema.Action.{action.Code}.Param";
            exprItem.RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(exprContent);
            exprItem.RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, exprContent, false);
            if (dType == DataType.List)
            {
                if (schema.Entity.ListTypeMethods != null)
                {
                    //增加List节点
                    schema.Entity.ListTypeMethods.OrderBy(x => x.SortOrder).ToList().ForEach(method =>
                    {
                        BuildListTypeMethodExprItem(exprItem, method, schema.Entity, true, IsContainExt, action);
                    });
                }
            }
            else if (dType == DataType.Record)
            {
                //增加Record节点
                var recordNode = new ExprItem()
                {
                    ID = "Record",
                    Code = "Record",
                    Name = "Record",
                    DisplayName = exprItem.DisplayName + ".Record",
                    RefSchemaExpr = provider.RefSchemaExprUtil.GetExpr(exprItem.RefSchemaExpr),
                    RefSchemaExprValue = provider.RefSchemaExprUtil.GetExprValue(refSchemaEntity, exprItem.RefSchemaExpr, false),
                    ItemType = ItemType.Object,
                    ValueType = DataType.Record,
                    HelpInfo = action.Code + "Record",
                    SortOrder = 0,
                    ExprMetaDataID = exprItem.ExprMetaDataID,
                    ParentID = exprItem.ID,
                    IsLeaf = false,
                    DataModels = schema.Entity.MetadataCode
                };
                recordNode.DataModels = schema.Entity.MetadataCode;
                BuildTEntityExprItem(recordNode, schema.Entity, IsContainExt, action);
                exprItem.Children.Add(recordNode);
            }
        }

        private void UpdateHelpInfo(ExprItem item)
        {
            switch (item.ItemType)
            {
                case ItemType.Action:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        helpInfo.Append($"Action:<b>{item.Code}</b> DataType <b>{item.DataModels}</b><br/>");
                        helpInfo.Append("<br/>");
                        helpInfo.Append($"Params:<br/>");
                        foreach (var p in item.ExprFuncItemParamList)
                        {
                            helpInfo.Append($"<b>{p.Code}</b> DataType: <b>{p.DataType}</b><br/>");
                        }
                        helpInfo.Append("<br/>");
                        helpInfo.Append($"ReturnValueType:<b>{item.ValueType}</b><br/>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.Attribute:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        helpInfo.Append($"<b>{item.Code}</b> DataType <b>{item.ValueType}</b><br/>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.DO:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        helpInfo.Append($"DataType <b>{item.DataModels} DO</b><br/>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.EO:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        helpInfo.Append($"DataType <b>{item.DataModels} EO</b><br/>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.Object:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        if (item.ValueType == DataType.List)
                        {
                            helpInfo.Append($"DataType <b>{item.DataModels} List</b><br/>");
                        }
                        else if (item.ValueType == DataType.Record)
                        {
                            helpInfo.Append($"DataType <b>{item.DataModels} Record</b><br/>");
                        }
                        else
                        {
                            helpInfo.Append($"DataType <b>{item.ValueType}</b><br/>");
                        }
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
            }
            if (item.Children != null)
            {
                item.Children.ForEach(c => UpdateHelpInfo(c));
            }
        }
        private ItemType GetItemTypeByTEntityType(TEntityType eType)
        {
            switch (eType)
            {
                case TEntityType.DO:
                    return ItemType.DO;
                case TEntityType.CDO:
                    return ItemType.DO;
                case TEntityType.SGEO:
                case TEntityType.EO:
                    return ItemType.EO;
                case TEntityType.Attribute:
                    return ItemType.Attribute;
                default:
                    return ItemType.Object;

            }
        }
    }
}
